package telltale;

import java.util.ArrayList;
import java.util.Date;

abstract class
	AbstractAdapter
implements
	Adapter
{
	public void log( TellTale telltale )
	{
		String entry = entry( telltale, null, null );
		persist( entry );
	}
	
	public void log( TellTale telltale, Object message )
	{
		String crazy = ( message == null ? "null" : message.toString() );
		String entry = entry( telltale, null, crazy );
		persist( entry );
	}
	
	public void log( TellTale telltale, String template, Object a )
	{
		checkTemplate( template );
		String message = String.format( template, a );
		String entry = entry( telltale, null, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, String template, Object a, Object b )
	{
		checkTemplate( template );
		String message = String.format( template, a, b );
		String entry = entry( telltale, null, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, String template, Object a, Object b, Object c )
	{
		checkTemplate( template );
		String message = String.format( template, a, b, c );
		String entry = entry( telltale, null, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, String template, Object... a )
	{
		checkTemplate( template );
		String message = String.format( template, a );
		String entry = entry( telltale, null, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable )
	{
		checkThrowable( throwable );
		String entry = entry( telltale, throwable, null );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable, Object message )
	{
		checkThrowable( throwable );
		String crazy = ( message == null ? "null" : message.toString() );
		String entry = entry( telltale, throwable, crazy );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable, String template, Object a )
	{
		checkThrowable( throwable );
		checkTemplate( template );
		String message = String.format( template, a );
		String entry = entry( telltale, throwable, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable, String template, Object a, Object b )
	{
		checkThrowable( throwable );
		checkTemplate( template );
		String message = String.format( template, a, b );
		String entry = entry( telltale, throwable, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable, String template, Object a, Object b, Object c )
	{
		checkThrowable( throwable );
		checkTemplate( template );
		String message = String.format( template, a, b, c );
		String entry = entry( telltale, throwable, message );
		persist( entry );
	}
	
	public void log( TellTale telltale, Throwable throwable, String template, Object... a )
	{
		checkThrowable( throwable );
		checkTemplate( template );
		String message = String.format( template, a );
		String entry = entry( telltale, throwable, message );
		persist( entry );
	}
	
	private final void checkTemplate( String template )
	{
		if( template == null )
		{
			throw new NullPointerException( "template" );
		}
	}
	
	private final void checkThrowable( Throwable throwable )
	{
		if( throwable == null )
		{
			throw new NullPointerException( "throwable" );
		}
	}
	
	private boolean _stackTrace = true;
	
	public synchronized void setStackTrace( boolean stackTrace ) 
	{ 
		_stackTrace = stackTrace; 
	}
	
	public synchronized boolean getStackTrace() 
	{ 
		return _stackTrace; 
	}
	
	public final static String DEFAULT_TEMPLATE = "{timestamp}tD {timestamp}tT | {thread}s | {longclass}s | {message}s";
//	public final static String DEFAULT_DAILY_DIRECTORY = ".";
//	public final static String DEFAULT_DAILY_PATTERN = "yyyy-MM-dd";
//	public final static String DEFAULT_DAILY_SUFFIX = "log";
	

	private String _template = DEFAULT_TEMPLATE;
	
	// TODO: Validate template (syntax)
	public void setTemplate( String template )
	{
		if( template == null )
		{
			throw new NullPointerException( "template" );
		}
		_template = template;
	}
	
	public String getTemplate() 
	{
		return _template;
	}
	
	private String replace( String template, String param, int nth ) 
	{
		StringBuilder sb = new StringBuilder();
		sb.append( '%' );
		sb.append( nth++ );
		sb.append( '$' );
		return template.replace( param, sb.toString() );
	}
	
	public String entry( TellTale telltale, Throwable throwable, String message )
	{
		String template = getTemplate();
		ArrayList<Object> _values = new ArrayList<Object>();
		
		int nth = 1;

		if( template.contains( "{timestamp}" ))
		{
			template = replace( template, "{timestamp}", nth++ );
			_values.add( new Date() );
		}
		if( template.contains( "{thread}" ))
		{
			template = replace( template, "{thread}", nth++ );
			String thread = Thread.currentThread().getName();
			_values.add( thread );
		}
		if( template.contains( "{longclass}" ))
		{
			template = replace( template, "{longclass}", nth++ );
			String longClass = telltale.getLongClass();
			_values.add( longClass );
		}
		if( template.contains( "{shortclass}" ))
		{
			template = replace( template, "{shortclass}", nth++ );
			String shortClass = telltale.getShortClass();
			_values.add( shortClass );
		}
		if( template.contains( "{message}" ))
		{
			template = replace( template, "{message}", nth++ );
			_values.add( message == null ? "" : message );
		}
		
		Object args[] = _values.toArray();
		String result = String.format( template, args );
		return result;

//		try
//		{
//			append( result );
//	
//			if( getStackTrace() && throwable != null )
//			{
//				StringWriter writer = new StringWriter();
//				PrintWriter printer = new PrintWriter( writer );
//				throwable.printStackTrace( printer );
//				append( writer.toString() );
//			}
//		}
//		catch( IOException e )
//		{
//			e.printStackTrace( System.err );
//		}
	}
	
	public abstract void persist( String entry );
	
}
